package mvc

import (
	"bytes"
	"fmt"
	"net/http"
	"relay-control/lib/utils"
	"relay-control/src/basic"
	"strings"
)

// Controller ...
type Controller func(request *http.Request, responseW http.ResponseWriter)

// Intercept ...
type Intercept func(request *http.Request, responseW http.ResponseWriter) (*http.Request, http.ResponseWriter)

func ListenHttp() {
	err := http.ListenAndServe(fmt.Sprintf("%s:%d", basic.LocalHost, basic.Port), &Handler{})
	utils.TryThrow(err)
}

type Handler struct {
}

func (h *Handler) ServeHTTP(responseW http.ResponseWriter, request *http.Request) {
	req, resW := interceptor(request, responseW)
	controller := findMapping(NewReq(req.Method, req.RequestURI))
	if controller != nil {
		handing(controller, req, resW)
	} else {
		resW.WriteHeader(http.StatusNotFound)
		_, err := resW.Write(bytes.NewBufferString("404 not find").Bytes())
		utils.TryThrow(err)
	}
}

func findMapping(r *Req) Controller {
	addr := r.Addr
	if strings.Contains(r.Addr, "?") {
		addr = strings.Split(r.Addr, "?")[0]
	}
	for k, v := range QuestMapping {
		if (k.Method == r.Method) && (k.Addr == addr) {
			return v
		}
	}
	return nil
}

func handing(fun Controller, request *http.Request, responseW http.ResponseWriter) {
	fun(request, responseW)
}

func interceptor(request *http.Request, responseW http.ResponseWriter) (*http.Request, http.ResponseWriter) {
	for i := range Interceptors {
		request, responseW = Interceptors[i](request, responseW)
	}
	return request, responseW
}
